/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.windows; import java.util.Set; import java.util.HashSet; import java.util.Iterator; import java.awt.Image; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.Point; import java.awt.Toolkit; import java.awt.Window; import java.text.MessageFormat; import java.util.ResourceBundle; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.ObjectStreamException; import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.IOException; import java.net.URL; import javax.swing.SwingUtilities; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import org.openide.windows.*; import org.openide.util.NbBundle; import org.openide.TopManager; import org.openide.awt.ToolbarPool; import org.openide.util.Mutex; import org.netbeans.core.output.OutputTab; import org.netbeans.core.windows.util.*; /** Implementation of the workspace interface. * * @author Dafe Simonek */ public final class WorkspaceImpl implements Workspace, DeferredPerformer.DeferredCommand { /** Name of property for the list of elements on this workspace. */ public static final String PROP_MODES = "modes"; // NOI18N /** Name of property for the name of this workspace. */ public static final String PROP_NAME = "name"; // NOI18N /** count number of workspaces */ static int numberOfWorkspaces = 0; /** Dimensions of the screen */ static Dimension screenSize; /** Information message shown during loading */ static MessageFormat loadingMessage; /** helper - last bounds of main window */ static Rectangle lastMainBounds; /** a pool of toolbars */ static ToolbarPool toolbarPool; /** cascading step */ Dimension cascadeStep = new Dimension(20, 20); private int cascadeStepsCount; /** Current cascade point - to which cascaded windows are placed */ Point cascadePoint; /** Origin of the cascading on this workspace */ Point cascadingOrigin; /** programmatic name of the workspace */ String name; /** display name of the workspace. actually, it serves two purposes. * if fromBundle helper variable is true, then displayName contains name * of the bundle string to take display name from. */ String displayName; /** toolbar configuration name */ String toolbarConfigName = "Standard"; // NOI18N /** A list of all modes on this workspace * @associates ModeImpl*/ HashSet modes; /** Currently activated mode */ Mode current; /** Helper flag variable, true if display name is taken from the bundle */ boolean fromBundle; /** holds previously active top component when * workspace was visible last time */ transient TopComponent savedActive; /** Helper variable - holds information needed * to renew activated top component after deserialization. */ WindowManagerImpl.TopComponentManager savedManager; /** true if this workspace is visible (current) */ transient boolean visible; /** asociation with window manager implementation */ transient WindowManagerImpl wm; /** property change support */ private transient PropertyChangeSupport changeSupport; /** default workspace name */ private static MessageFormat defaultWorkspaceName; /** manager of versioned serialization */ private VersionSerializator serializationManager; /** Default height and width of modes */ static final int DEFAULT_MODE_WIDTH = 500; static final int DEFAULT_MODE_HEIGHT = 350; static final long serialVersionUID =-1865300855714270375L; /** Creates new workspace implementation with generated default name * and display name */ public WorkspaceImpl () { this((String)null); } /** Creates new workspace implementation with given name. * Given parameter is used both for name and display name. */ public WorkspaceImpl (String name) { this(name, name, false); } /** Creates new workspace with given programmatic name and * given display name. */ public WorkspaceImpl (String name, String displayName) { this(name, displayName, false); } /** Creates new workspace with given programmatic name and * given display name. * @param fromBundle true if displayName parameter contains bundle string * rather than real display name */ public WorkspaceImpl (String name, String displayName, boolean fromBundle) { this.name = name; this.fromBundle = fromBundle; if (name == null) { // set default name Object[] arr = { new Integer (++numberOfWorkspaces) }; if (defaultWorkspaceName == null) { ResourceBundle bundle = NbBundle.getBundle (WorkspaceImpl.class); defaultWorkspaceName = new MessageFormat (bundle.getString ("WorkspaceNumber")); } this.name = defaultWorkspaceName.format (arr); } // display name this.displayName = (displayName == null) ? this.name : displayName; modes = new HashSet(10); initialize(); } /** Copy constructor, creates new workspace as a copy of given workspace. * Created workspace will have a list of modes with the same names, * bounds etc as the original, and the same top components will * be opened on the clone as they are in the original. * The name of cloned workspace will be unique, based on the * name of the original. */ public WorkspaceImpl (WorkspaceImpl original) { // usual initialization modes = new HashSet(10); initialize(); // create a name int i = 1; while (wm.findWorkspace(name = original.name + "_" + i++) != null); // NOI18N // display name displayName = original.getDisplayName() + (i - 1); // copy content this.cascadeStep = new Dimension(original.cascadeStep); this.cascadeStepsCount = original.cascadeStepsCount; this.cascadePoint = (original.cascadePoint == null) ? null : new Point(original.cascadePoint); this.toolbarConfigName = new String(original.toolbarConfigName); // copy modes ModeImpl curMode = null; ModeImpl newMode = null; for (Iterator iter = original.modes.iterator(); iter.hasNext(); ) { curMode = (ModeImpl)iter.next(); newMode = new ModeImpl(this, curMode); if (curMode.equals(original.current)) { this.current = newMode; } modes.add(newMode); // copy reference to the contained tcs newMode.fillTopComponents(curMode); } } private void initialize () { if (screenSize == null) { screenSize = Toolkit.getDefaultToolkit().getScreenSize(); } changeSupport = new PropertyChangeSupport(this); wm = (WindowManagerImpl)TopManager.getDefault().getWindowManager(); cascadingOrigin = new Point(0, 0); } /** Get the programmatic unique name of this workspace. * @return the programmatic name */ public String getName () { return name; } /** Get human-presentable name of the workspace. * May be used, e.g., for display on the workspaces tab on the main window. * @return the diplay name of the workspace */ public String getDisplayName () { return fromBundle ? NbBundle.getBundle(WorkspaceImpl.class).getString(displayName) : displayName; } /** Set human-presentable name of the workspace. * @param s the new display name */ public void setDisplayName (String s) { String localDisplay = getDisplayName(); if (((localDisplay != null) && localDisplay.equals(s)) || (localDisplay == null) && (s == null)) { // no real change return; } // disable fromBundle feature, it user's choice now fromBundle = false; String old = displayName; displayName = s; changeSupport.firePropertyChange (PROP_DISPLAY_NAME, old, displayName); } /** Array of all modes on this workspace. */ public Set getModes () { return modes; } /** Get bounds of the workspace. * Delegates to static getWorkingSpaceBounds(). */ public Rectangle getBounds () { return getWorkingSpaceBounds(); } /** Activates this workspace to be current one. * This leads to change of current workspace of the WindowManager. */ public void activate () { wm.setCurrentWorkspace(this); } /** Create a new mode. * @param name a unique programmatic name of the mode * @param displayName a human presentable (probably localized) name * of the mode (may be used by *{@link org.openide.actions.DockingAction}, e.g.) * @param icon an icon to use for the mode (e.g. on a tab or window corner); * may be <code>null</code> * @return the new mode */ public Mode createMode (String name, String displayName, URL icon) { return createMode(name, displayName, icon, ModeImpl.MULTI_TAB, false); } /** Create new mode. * @param name a unique programmatic name of the mode * @param displayName a human presentable (probably localized) name * of the mode (may be used by *{@link org.openide.actions.DockingAction}, e.g.) * @param icon an icon to use for the mode (e.g. on a tab or window corner); * may be <code>null</code> * @return the new mode * @param containerType type specifies type of frame representing * the mode * @param userDefined true if mode is creted by user */ public Mode createMode (String name, String displayName, URL icon, int containerType, boolean userDefined) { // throw exception when method is used wrongly if (name == null) { throw new IllegalArgumentException("Cannot create mode with null name!"); // NOI18N } Mode newMode = findMode(name); if (newMode == null) { newMode = new ModeImpl(name, displayName, icon, containerType, userDefined, this); addMode(newMode); } return newMode; } /** Search all modes on this workspace by name. * @param name the name of the mode to search for * @return the mode with that name, or <code>null</code> if no such mode * can be found */ public Mode findMode (String name) { if (name == null) { return null; } Mode[] modeArray = (Mode[])modes.toArray(new Mode[0]); for (int i = 0; i < modeArray.length; i++) { if (name.equals(modeArray[i].getName())) return modeArray[i]; } return null; } /** Finds mode the component is in on this workspace. * * @param c component to find mode for * @return the mode or null if the component is not visible on this workspace */ public Mode findMode (TopComponent c) { if (modes == null) { if (System.getProperty("netbeans.debug.exceptions") != null) { System.out.println("Inconsistent state!"); // NOI18N System.out.println("Modes null....."); // NOI18N System.out.println("Workspace: " + getName()); // NOI18N Thread.dumpStack(); } } Mode[] modeArray = (Mode[])modes.toArray(new Mode[0]); for (int i = 0; i < modeArray.length; i++) { TopComponent[] tcs = modeArray[i].getTopComponents(); for (int y = 0; y < tcs.length; y++) { if (c.equals(tcs[y])) { // System.out.println("Found # " + y + " " + tcs[y].getName()); // NOI18N return modeArray[i]; } } } return null; } /** @return true if given top component is opened on this workspace, * false otherwise */ public boolean isOpened (TopComponent tc) { return wm.findManager(tc).isOpened(this); } /** Clears this workspace and removee this workspace from * window manager, if possible */ public void remove () { // clear the workspace if (!modes.isEmpty()) { // iterate through modes and try to close them ModeImpl[] modeArray = (ModeImpl[])modes.toArray(new ModeImpl[0]); for (int i = 0; i < modeArray.length; i++) { modeArray[i].close(); } modes.clear(); // fire changes changeSupport.firePropertyChange(PROP_MODES, null, null); } // remove this workspace Workspace[] wss = wm.getWorkspaces(); int i = 0; for (i = 0; i < wss.length; i++) { if (this.equals(wss[i])) { break; } } if (i < wss.length) { Workspace[] nwss = new Workspace[wss.length-1]; System.arraycopy(wss, 0, nwss, 0, i); System.arraycopy(wss, i + 1, nwss, i, wss.length - (i + 1)); wm.setWorkspaces(nwss); } } /** Add a property change listener. * @param list the listener to add */ public void addPropertyChangeListener (PropertyChangeListener l) { changeSupport.addPropertyChangeListener(l); } /** Remove a property change listener. * @param list the listener to remove */ public void removePropertyChangeListener (PropertyChangeListener l) { changeSupport.removePropertyChangeListener(l); } /** Shows or hides all content of this workspace. */ public synchronized void setVisible (boolean visible) { if (this.visible == visible) return; if (visible && (!wm.deferredPerformer().canImmediatelly())) { // show workspace later wm.deferredPerformer().putRequest(this, null); return; } this.visible = visible; // save active for later reactivation if hiding if (!visible) { savedActive = TopComponent.getRegistry().getActivated(); if ((savedActive != null) && (findMode(savedActive) == null)) savedActive = null; wm.activateComponent(null); if (savedActive != null) { //System.out.println("Saved: " + savedActive.getName()); // NOI18N } } // set visibility for all modes for (Iterator iter = modes.iterator(); iter.hasNext(); ) { ((ModeImpl)iter.next()).setVisible(visible); } // update toolbar configuration and active component if (visible) { activateConfiguration(); if (savedActive != null) { // request focus later SwingUtilities.invokeLater(new Runnable () { public void run () { // synchronized to prevent from bug #5539 synchronized (WorkspaceImpl.this) { if (savedActive != null) { savedActive.requestFocus(); savedActive = null; } } } }); } else { // activation after deserialization reactivateSavedTc(); } } } /** Implementation of DeferredPerformer.DeferredCommand interface. * Sets this workspace to be visible. */ public void performCommand (Object context) { setVisible(true); } public boolean isVisible () { return visible; } /** * @return toolbar configuration name */ public String getToolbarConfigName () { return toolbarConfigName; } /** * Sets toolbar configuration for workspace * @param name of toolbar configuration for this workspace */ public void setToolbarConfigName (String name) { toolbarConfigName = name; if (this.equals(wm.getCurrentWorkspace())) activateConfiguration(); } /** * Prepare toolbar configuration */ void activateConfiguration () { if (toolbarPool == null) toolbarPool = ToolbarPool.getDefault(); //System.out.println("Setting: " + toolbarConfigName); // NOI18N toolbarPool.setConfiguration (toolbarConfigName); } /** Adds given mode to this workspace. */ public synchronized void addMode (Mode mode) { modes.add(mode); changeSupport.firePropertyChange(PROP_MODES, null, null); } /** Removes given mode from this workspace. */ public synchronized void removeMode (Mode mode) { modes.remove(mode); changeSupport.firePropertyChange(PROP_MODES, null, null); } /** Sets new cascading origin for this workspace. * Cascading origin is specified using percentage and * relative to left upper corner of IDE desktop * (main window's left bottom corner for SDI, * left bottom corner of main toolbar and workspace panel for MDI.<br> * So - setCascadingOrigin(0, 0) means upper left corner, * setCascadingOrigin(100, 100) means bottom right * corner of "IDE working space" */ public void setCascadingOrigin (Point cascadingOrigin) { this.cascadingOrigin = cascadingOrigin; recomputeCascadePoint(); } /* @return Current cascading origin for this workspace */ public Point getCascadingOrigin () { return cascadingOrigin; } /** Utility method which activates top component that was active * before serialization. */ private void reactivateSavedTc () { if (savedManager == null) { return; } final TopComponent toBeActivated = savedManager.getComponent(); /* System.out.println("Saved manager: " + savedManager); System.out.println("Saved tc: " + savedManager.getComponent()); */ savedManager = null; // component can be resolved to null after bad serialization, // be prepared to such situation if (toBeActivated != null) { // delay focus transferring and pass it to the AWT Event queue SwingUtilities.invokeLater(new Runnable() { public void run () { toBeActivated.requestFocus(); } }); } } /** Corrects the bounds of given list of modes */ private void correctBounds (Set modes) { // correct the size if the screen is different Dimension currentScreen = Toolkit.getDefaultToolkit().getScreenSize (); // do nothing if the same if (screenSize.equals (currentScreen)) return; double dx = ((double)currentScreen.width) / ((double)screenSize.width); double dy = ((double)currentScreen.height) / ((double)screenSize.height); // correct the bounds of modes Mode curMode = null; for (Iterator iter = modes.iterator(); iter.hasNext(); ) { curMode = (Mode)iter.next(); Rectangle r = (Rectangle)curMode.getBounds(); if (r != null) { r.x = (int)(r.x * dx); r.y = (int)(r.y * dy); r.width = (int)(r.width * dx); r.height = (int)(r.height * dy); curMode.setBounds(r); } } } /** @return Current cascade point of this workspace. Cascade point * is a point where mode screen representation (window, internal * frame or whatever) will be placed when added to this workspace. */ Point getCascadePoint () { Window mainWindow = wm.getMainWindow(); Rectangle mainBounds = mainWindow.getBounds(); // check variables if (lastMainBounds == null) lastMainBounds = mainBounds; if (cascadeStepsCount <= 0) cascadePoint = null; // recompute cascade point if needed if ((cascadePoint == null) || (!lastMainBounds.equals(mainBounds)) || (((mainBounds.width == 0) && (mainBounds.height == 0)))) { recomputeCascadePoint(); lastMainBounds = mainBounds; } return cascadePoint; } /** Recomputes location of the cascading point. Called when * no cascade point is computed yet or when dimensions of * IDE working space (either in SDI or MDI) has changed. */ private void recomputeCascadePoint () { // obtain IDE working space Rectangle workingSpace = getWorkingSpaceBounds(); // compute new cascading point cascadePoint = new Point( workingSpace.x + (cascadingOrigin.x * workingSpace.width / 100), workingSpace.y + (cascadingOrigin.y * workingSpace.height / 100) ); // now compute how deep cascade could be int xSteps, ySteps; if (cascadeStep.width < 0) { xSteps = Math.abs( (cascadingOrigin.x * workingSpace.width / 100) / cascadeStep.width ); } else { xSteps = Math.abs( ((100 - cascadingOrigin.x) * workingSpace.width / 100) / cascadeStep.width ); } if (cascadeStep.height < 0) { ySteps = Math.abs( (cascadingOrigin.y * workingSpace.height / 100) / cascadeStep.height ); } else { ySteps = Math.abs( ((100 - cascadingOrigin.y) * workingSpace.height / 100) / cascadeStep.height ); } cascadeStepsCount = Math.min(xSteps, ySteps) / 2; } /** Returns bounds for working space of the IDE. called from * getBounds() method. */ static Rectangle getWorkingSpaceBounds () { Rectangle mainBounds = TopManager.getDefault().getWindowManager().getMainWindow().getBounds(); Rectangle workingSpace = null; // SDI case int bottomSpace = 0; if (org.openide.util.Utilities.isWindows()) { bottomSpace = OutputTab.TYPICAL_WINDOWS_TASKBAR_HEIGHT; } if (mainBounds.y < (screenSize.height / 2)) { workingSpace = new Rectangle( 0, mainBounds.y + mainBounds.height, screenSize.width, screenSize.height - bottomSpace - (mainBounds.y + mainBounds.height) ); } else { workingSpace = new Rectangle( 0, 0, screenSize.width, mainBounds.y ); } // MDI case - PENDING - TBD return workingSpace; } /** Compute the bounds for the mode according to the current * cascading point and preferred size of given top component. * Update (move) cascading point. * This methoid is used when no mode bounds are specified explixitly. */ void placeMode (Mode mode, TopComponent tc) { // check if (mode.getBounds() != null) return; // compute Rectangle modeBounds = new Rectangle(); // start in cascading point Point cascadePoint = getCascadePoint(); modeBounds.x = cascadePoint.x; modeBounds.y = cascadePoint.y; // set size like top component wishes, if possible Dimension d = tc.getPreferredSize(); if ((d == null) || ((d.width == 0) && (d.height == 0))) { // set default size modeBounds.width = Math.min(DEFAULT_MODE_WIDTH, screenSize.width - modeBounds.x); modeBounds.height = Math.min(DEFAULT_MODE_HEIGHT, screenSize.height - modeBounds.y); } else { // the bounds must not exceed screen bounds modeBounds.width = Math.min(d.width, screenSize.width - modeBounds.x); modeBounds.height = Math.min(d.height, screenSize.height - modeBounds.y); } // update cascading point cascadePoint.x += cascadeStep.height; cascadePoint.y += cascadeStep.width; cascadeStepsCount--; // finally place the mode mode.setBounds(modeBounds); } /** Getter for the formatted information message during loading */ static MessageFormat getLoadingMessage () { if (loadingMessage == null) { loadingMessage = new MessageFormat(NbBundle.getBundle(Workspace.class). getString("FMT_LoadingWorkspace")); } return loadingMessage; } /** Utility method, removes modes which are user defined and * orphan from the given set of the modes */ void excludeUserOrphans (Set modes) { ModeImpl curMode = null; // just for debugging if ((modes == null) && (System.getProperty("netbeans.debug.exceptions") != null)) { System.out.println("Workspace in inconsistent state!"); // NOI18N System.out.println("Name: " + getName()); // NOI18N Thread.dumpStack(); } ModeImpl[] modeArray = (ModeImpl[])modes.toArray(new ModeImpl[0]); for (int i = 0; i < modeArray.length; i++) { if (modeArray[i].isUserDefined() && modeArray[i].isOrphan()) { //System.out.println("Excluding " + modeArray[i].getName()); // NOI18N modes.remove(modeArray[i]); } } } /** Accessor to the versioned serialization manager */ private VersionSerializator serializationManager () { if (serializationManager == null) { serializationManager = createSerializationManager(); } return serializationManager; } /** Creates new serialization manager filled with our versions */ private static VersionSerializator createSerializationManager () { VersionSerializator result = new VersionSerializator(); result.putVersion(new Version1()); result.putVersion(new Version2()); result.putVersion(new Version3()); return result; } /** Let instance of properly parametrized DefaultReplacer to keep * persistent state of this workspace */ private Object writeReplace () throws ObjectStreamException { // exclude unwanted modes (user defined orphans) excludeUserOrphans(modes); // provide versions with data Version1 version = (Version1)serializationManager().getVersion(Version1.NAME); version.assignData(this); version = (Version1)serializationManager().getVersion(Version2.NAME2); version.assignData(this); version = (Version1)serializationManager().getVersion(Version3.NAME3); version.assignData(this); // use replacer return new DefaultReplacer(new VSAccess(serializationManager())); } /** Called when first phase of WS deserialization is done. * Ask all contained modes for self validation. */ void validateSelf () { // turn to array to prevent concurrent modifications ModeImpl[] modeArray = (ModeImpl[])modes.toArray(new ModeImpl[modes.size()]); // validate modes themself for (int i = 0; i < modeArray.length; i++) { modeArray[i].validateSelf(this); } } /** Called after validateSelf() as second validation step. * Ask all contained modes data validation. */ void validateData () { // turn to array to prevent concurrent modifications ModeImpl[] modeArray = (ModeImpl[])modes.toArray(new ModeImpl[modes.size()]); // validate data (top component containers and top components) for (int i = 0; i < modeArray.length; i++) { modeArray[i].validateData(); } } /** Basic version of persistence for workspace implementation. * Method assignData(workspace) must be call before writing */ private static class Version1 implements DefaultReplacer.ResVersionable { /* identification string */ public static final String NAME = "Version_1.0"; // NOI18N /** variables which form persistent state of the workspace */ String name; String displayName; Dimension cascadeStep; int cascadeStepsCount; Point cascadePoint; String toolbarConfigName; HashSet modes; Mode current; /** asociation with workspace to be written, used during writing */ WorkspaceImpl workspace; /** Identification of the version */ public String getName () { return NAME; } /** Assigns data to be written. Must be called before writing */ public synchronized void assignData (WorkspaceImpl workspace) { this.workspace = workspace; } /** read the data of the version from given input */ public void readData (ObjectInput in) throws IOException, ClassNotFoundException { // read fields name = (String)in.readObject(); displayName = (String)in.readObject(); cascadeStep = (Dimension)in.readObject(); cascadeStepsCount = ((Integer)in.readObject()).intValue(); cascadePoint = (Point)in.readObject(); toolbarConfigName = (String)in.readObject(); modes = (HashSet)in.readObject(); current = (Mode)in.readObject(); } /** write the data of the version to given output */ public synchronized void writeData (ObjectOutput out) throws IOException { // write fields out.writeObject(workspace.name); out.writeObject(workspace.displayName); out.writeObject(workspace.cascadeStep); out.writeObject(new Integer(workspace.cascadeStepsCount)); out.writeObject(workspace.cascadePoint); out.writeObject(workspace.toolbarConfigName); out.writeObject(workspace.modes); out.writeObject(workspace.current); } /** First tries to resolve to existing workspace with the name * equal to deserialized name. If no such workspace can be found, * returns properly initialized newly created instance of workspace * implementation */ public Object resolveData () throws ObjectStreamException { WorkspaceImpl result = (WorkspaceImpl) TopManager.getDefault().getWindowManager().findWorkspace(name); if (result == null) { // workspace don't exist, create new one and fill it result = new WorkspaceImpl(name); result.displayName = displayName; result.cascadeStep = cascadeStep; result.cascadeStepsCount = cascadeStepsCount; result.cascadePoint = cascadePoint; result.toolbarConfigName = toolbarConfigName; result.modes = modes; result.current = current; } else { // try to add modes that don't exist yet in the workspace, // but leave other attributes untouched Mode curMode = null; for (Iterator iter = modes.iterator(); iter.hasNext(); ) { curMode = (Mode)iter.next(); if (result.findMode(curMode.getName()) == null) { result.addMode(curMode); } } } return result; } } // end of Version1 inner class /** Enhanced serialization protocol - adds cascading origin, * identification of last activated top component */ private static class Version2 extends Version1 { /* identification string */ public static final String NAME2 = "Version_2.0"; // NOI18N Point cascadingOrigin; WindowManagerImpl.TopComponentManager savedManager; /** Identification of the version */ public String getName () { return NAME2; } /** read the data of the version from given input */ public void readData (ObjectInput in) throws IOException, ClassNotFoundException { super.readData(in); cascadingOrigin = (Point)in.readObject(); savedManager = (WindowManagerImpl.TopComponentManager)in.readObject(); } /** write the data of the version to given output */ public synchronized void writeData (ObjectOutput out) throws IOException { // write fields super.writeData(out); out.writeObject(workspace.cascadingOrigin); TopComponent tc = (workspace.savedActive == null) ? TopComponent.getRegistry().getActivated() : workspace.savedActive; if ((tc != null) && (tc.isOpened(workspace))) { out.writeObject(WindowManagerImpl.findManager(tc)); } else { out.writeObject(null); } } public Object resolveData () throws ObjectStreamException { WorkspaceImpl result = (WorkspaceImpl)super.resolveData(); WorkspaceImpl existing = (WorkspaceImpl) TopManager.getDefault().getWindowManager().findWorkspace(this.name); if (existing == null) { // workspace didn't exist, fill it result.cascadingOrigin = cascadingOrigin; result.savedManager = savedManager; } return result; } } // end of Version2 inner class /** Enhanced serialization protocol - adds fromBundle flag */ private static class Version3 extends Version2 { /* identification string */ public static final String NAME3 = "Version_3.0"; // NOI18N boolean fromBundle; /** Identification of the version */ public String getName () { return NAME3; } /** read the data of the version from given input */ public void readData (ObjectInput in) throws IOException, ClassNotFoundException { super.readData(in); fromBundle = ((Boolean)in.readObject()).booleanValue(); } /** write the data of the version to given output */ public synchronized void writeData (ObjectOutput out) throws IOException { // write fields super.writeData(out); out.writeObject(new Boolean(workspace.fromBundle)); } public Object resolveData () throws ObjectStreamException { WorkspaceImpl result = (WorkspaceImpl)super.resolveData(); WorkspaceImpl existing = (WorkspaceImpl) TopManager.getDefault().getWindowManager().findWorkspace(this.name); if (existing == null) { // workspace didn't exist, fill it result.fromBundle = fromBundle; } return result; } } // end of Version3 inner class /** Implementation of persistent access to our version serializator */ private static final class VSAccess implements DefaultReplacer.Access { /** serialVersionUID */ private static final long serialVersionUID = 2367034636261092266L; /** version serializator, used only during writing */ transient VersionSerializator vs; public VSAccess (VersionSerializator vs) { this.vs = vs; } public VersionSerializator getVersionSerializator () { return (vs == null) ? createSerializationManager() : vs; } } // end of VSAccess inner class } /* * Log * 36 Gandalf-post-FCS1.32.1.2 4/20/00 David Simonek * 35 Gandalf-post-FCS1.32.1.1 4/20/00 David Simonek * 34 Gandalf-post-FCS1.32.1.0 4/20/00 David Simonek from bundle added * 33 Gandalf 1.32 2/25/00 David Simonek #5859 bugfix * 32 Gandalf 1.31 1/15/00 David Simonek mutliwindow title bug * fixed * 31 Gandalf 1.30 1/13/00 David Simonek i18n * 30 Gandalf 1.29 1/12/00 Ian Formanek NOI18N * 29 Gandalf 1.28 1/10/00 David Simonek minor changes connected * with focus problematics * 28 Gandalf 1.27 12/17/99 David Simonek #1913, #2970 * 27 Gandalf 1.26 12/6/99 David Simonek method getBounds() added * 26 Gandalf 1.25 11/30/99 David Simonek neccessary changes needed * to change main explorer to new UI style (tabs are full top components * now, visual workspace added, layout of editing workspace chnaged a bit) * 25 Gandalf 1.24 11/10/99 David Simonek debug comments removed * 24 Gandalf 1.23 11/6/99 David Simonek serialization bug fixing * 23 Gandalf 1.22 11/4/99 David Simonek ws serialization bugfixes * 22 Gandalf 1.21 11/3/99 David Simonek completely rewritten * serialization of windowing system... * 21 Gandalf 1.20 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 20 Gandalf 1.19 10/7/99 David Simonek debug prints removed... * 19 Gandalf 1.18 10/6/99 David Simonek more robust serialization * of window system (especially editor TCs) * 18 Gandalf 1.17 9/8/99 David Simonek deferred opening and * firing of selected nodes, state management * 17 Gandalf 1.16 8/18/99 Ian Formanek Generated serial version * UID * 16 Gandalf 1.15 8/17/99 David Simonek persistent main window * positioning issues * 15 Gandalf 1.14 8/14/99 David Simonek bugfixes, #3347, #3274 * etc. * 14 Gandalf 1.13 8/9/99 David Simonek * 13 Gandalf 1.12 8/1/99 David Simonek debug prints commented * 12 Gandalf 1.11 8/1/99 David Simonek * 11 Gandalf 1.10 7/31/99 David Simonek small additions * 10 Gandalf 1.9 7/30/99 David Simonek serialization fixes * 9 Gandalf 1.8 7/30/99 David Simonek iconification bugfixes, * focus bugfixes * 8 Gandalf 1.7 7/29/99 David Simonek further ws serialization * changes * 7 Gandalf 1.6 7/28/99 David Simonek serialization of window * system...first draft :-) * 6 Gandalf 1.5 7/22/99 Libor Kramolis * 5 Gandalf 1.4 7/21/99 David Simonek window system updates... * 4 Gandalf 1.3 7/20/99 David Simonek various window system * updates * 3 Gandalf 1.2 7/12/99 Jaroslav Tulach Fixed a * NullPointerException * 2 Gandalf 1.1 7/12/99 Jaroslav Tulach To be compilable. * 1 Gandalf 1.0 7/11/99 David Simonek * $ */